#include <glfw.h>
#include <stdlib.h> 
#include <iostream>
using namespace std;

void Init(void);
void ShutDown(int return_code);
void MainLoop(void);
void Draw_Square(float red, float green, float blue);
void Draw(void);

float rotate_y = 0,
      rotate_z = 0;
const float rotations_per_tick = .2;

int main()
{
	Init();
	MainLoop();
	ShutDown(0);
}

void Init()
{
	const int window_width = 800,
            window_height = 600;
 
	  if (glfwInit() != GL_TRUE)
		ShutDown(1);
	  // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed
	  if (glfwOpenWindow(window_width, window_height, 5, 6, 5,
						 0, 0, 0, GLFW_WINDOW) != GL_TRUE)
		ShutDown(1);
	  glfwSetWindowTitle("The GLFW Window");
 
	  // set the projection matrix to a normal frustum with a max depth of 50
	  glMatrixMode(GL_PROJECTION);
	  glLoadIdentity();
	  float aspect_ratio = ((float)window_height) / window_width;
	  glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50);
	  glMatrixMode(GL_MODELVIEW);
}

void MainLoop()
{
	// the time of the previous frame
  double old_time = glfwGetTime();
  // this just loops as long as the program runs
  while(1)
  {
    // calculate time elapsed, and the amount by which stuff rotates
    double current_time = glfwGetTime(),
           delta_rotate = (current_time - old_time) * rotations_per_tick * 360;
    old_time = current_time;
    // escape to quit, arrow keys to rotate view
    if (glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS)
      break;
    if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS)
      rotate_y += delta_rotate;
    if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS)
      rotate_y -= delta_rotate;
    // z axis always rotates
    rotate_z += delta_rotate;
 
    // clear the buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // draw the figure
    Draw();
    // swap back and front buffers
    glfwSwapBuffers();
  }
}

void Draw_Square(float red, float green, float blue)
{
  // Draws a square with a gradient color at coordinates 0, 10
  glBegin(GL_QUADS);
  {
    glColor3f(red, green, blue);
    glVertex2i(1, 11);
    glColor3f(red * .8, green * .8, blue * .8);
    glVertex2i(-1, 11);
    glColor3f(red * .5, green * .5, blue * .5);
    glVertex2i(-1, 9);
    glColor3f(red * .8, green * .8, blue * .8);
    glVertex2i(1, 9);
  }
  glEnd();
}
 
void Draw(void)
{
  // reset view matrix
  glLoadIdentity();
  // move view back a bit
  glTranslatef(0, 0, -30);
  // apply the current rotation
  glRotatef(rotate_y, 0, 1, 0);
  glRotatef(rotate_z, 0, 0, 1);
  // by repeatedly rotating the view matrix during drawing, the
  // squares end up in a circle
  int i = 0, squares = 15;
  float red = 0, blue = 1;
  for (; i < squares; ++i){
    glRotatef(360.0/squares, 0, 0, 1);
    // colors change for each square
    red += 1.0/12;
    blue -= 1.0/12;
    Draw_Square(red, .6, blue);
  }
}

void ShutDown(int returncode)
{
	glfwTerminate();
	exit(returncode);
}

//#include <glfw.h>
//#include <stdlib.h>  //needed for exit function
//#include <iostream>
//using namespace std;
//
//static const GLfloat g_vertex_buffer_data[] = {
//   -1.0f, -1.0f, 0.0f,
//   1.0f, -1.0f, 0.0f,
//   0.0f,  1.0f, 0.0f,
//};
//
//void initializeRendering()
//{
//	glfwInit();
//	//Makes 3D drawing work when something is in front of something else
//	glEnable(GL_DEPTH_TEST);
//}
//
//void GLFWCALL handleKeypress(int key,int press) //The key that was pressed
//{
//    switch (key) {
//        case GLFW_KEY_ESC: //Escape key
//            exit(0); //Exit the program
//    }
//}
//
//void GLFWCALL handleResize(int width,int height)
//{
//    //Tell OpenGL how to convert from coordinates to pixel 
//    glViewport( 0, 0, width, height );
//
//    glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective
//    //Set the camera perspective
//    glLoadIdentity(); //reset the camera
//    gluPerspective( 45.0f,                      //camera angle
//                (GLfloat)width/(GLfloat)height, //The width to height ratio
//                 1.0f,                          //The near z clipping coordinate
//                100.0f );                       //The far z clipping coordinate
//}
//
//GLuint loadBMP_custom(const char * imagepath)
//{
//	// Data read from the header of the BMP file
//	unsigned char header[54]; // Each BMP file begins by a 54-bytes header
//	unsigned int dataPos;     // Position in the file where the actual data begins
//	unsigned int width, height;
//	unsigned int imageSize;   // = width*height*3
//	// Actual RGB data
//	unsigned char * data;
//
//	// Open the file
//	FILE * file = fopen(imagepath,"rb");
//	if (!file)
//	{
//		printf("Image could not be opened\n"); 
//		return 0;
//	}
//	if ( fread(header, 1, 54, file)!=54 )
//	{ // If not 54 bytes read : problem
//		printf("Not a correct BMP file\n");
//		return false;
//	}
//	if ( header[0]!='B' || header[1]!='M' )
//	{
//		printf("Not a correct BMP file\n");
//		return 0;
//	}
//	// Read ints from the byte array
//	dataPos    = *(int*)&(header[0x0A]);
//	imageSize  = *(int*)&(header[0x22]);
//	width      = *(int*)&(header[0x12]);
//	height     = *(int*)&(header[0x16]);
//
//	// Some BMP files are misformatted, guess missing information
//	if (imageSize==0)    imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
//	if (dataPos==0)      dataPos=54; // The BMP header is done that way
//
//	// Create a buffer
//	data = new unsigned char [imageSize];
// 
//	// Read the actual data from the file into the buffer
//	fread(data,1,imageSize,file);
// 
//	//Everything is in memory now, the file can be closed
//	fclose(file);
//
//	// Create one OpenGL texture
//	GLuint textureID;
//	glGenTextures(1, &textureID);
// 
//	// "Bind" the newly created texture : all future texture functions will modify this texture
//	glBindTexture(GL_TEXTURE_2D, textureID);
// 
//	// Give the image to OpenGL
//	glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, data);
// 
//	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//}
//
//GLuint LoadTexture(const char* TextureName)
//{
//   GLuint Texture;  //variable for texture
//   glGenTextures(1,&Texture); //allocate the memory for texture
//   glBindTexture(GL_TEXTURE_2D,Texture); //Binding the texture
//
//   if(glfwLoadTexture2D(TextureName, GLFW_BUILD_MIPMAPS_BIT)){
//      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
//      return Texture;
//   }
//   else return -1;
//}
//
//void display()
//{
//	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black
//    //Clear information from last draw
//    glClear( GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//    glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
//
//	glLoadIdentity(); //Reset the drawing perspective
//
//    /*glTranslatef(0.0f,0.0f,-35.0f); //Translate whole scene to -ve z-axis by -35 unit
//
//    GLuint text2D;
//    text2D = LoadTexture("cicb.tga"); //loading image for texture
//
//    glEnable(GL_TEXTURE_2D); //Enable texture
//    glBindTexture(GL_TEXTURE_2D,text2D);//Binding texture
//
//    glPushMatrix();
//    glBegin(GL_POLYGON); //Begin quadrilateral coordinates
//    glNormal3f(0.0f, 0.0f, 1.0f);//normal vector
//	glTexCoord2f(0.0f, 0.0f); //Texture co-ordinate origin or  lower left corner
//	glVertex3f(-10.0f,-11.0f,5.0f);
//	glTexCoord2f(1.0f, 0.0f); //Texture co-ordinate lower right corner
//	glVertex3f(10.0f,-11.0f,5.0f);
//	glTexCoord2f(1.0f, 1.0f);//Texture co-ordinate top right corner
//	glVertex3f(10.0f,-1.0f,-15.0f);
//	glTexCoord2f(0.0f, 1.0f);//Texture co-ordinate top left corner
//	glVertex3f(-10.0f,-1.0f,-15.0f);
//	glEnd(); //End quadrilateral coordinates
//	glPopMatrix();
//	glDisable(GL_TEXTURE_2D);
//
//	glEnable(GL_TEXTURE_2D);
//    glBindTexture(GL_TEXTURE_2D,text2D);
//    glPushMatrix();
//    glBegin(GL_POLYGON);
//    glNormal3f(0.0f, 0.0f, 1.0f);
//	glTexCoord2f(0.0f, 0.0f);//Texture co-ordinate origin or lower left corner
//    glVertex3f(-10.0f,-1.0f,-15.0f);
//    glTexCoord2f(10.0f, 0.0f); //Texture co-ordinate for repeating image ten times form
//    //origin to lower right corner
//    glVertex3f(10.0f,-1.0f,-15.0f);
//    glTexCoord2f(10.0f, 10.0f);//repeat texture ten times form lower to top right corner.
//    glVertex3f(10.0f,15.0f,-15.0f);
//    glTexCoord2f(0.0f, 10.0f);//repeat texture ten time form top right to top left corner.
//    glVertex3f(-10.0f,15.0f,-15.0f);
//    glEnd();
//    glPopMatrix();
//
//    glDisable(GL_TEXTURE_2D); //Disable the texture
//    glfwSwapBuffers();*/
//
//    /*glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black
//    //Clear information from last draw
//    glClear( GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//    glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
//
//	glPushMatrix();
//	glTranslatef(0.0f,0.0f,-35.0f); //Translate whole scene to -ve z-axis by -35 unit
//
//    glLoadIdentity(); //Reset the drawing perspective
//    glBegin(GL_QUADS); //Begin quadrilateral coordinates
//    //Trapezoid
//    glVertex3f(-0.7f, -1.5f, -5.0f);
//    glVertex3f(0.7f, -1.5f, -5.0f);
//    glVertex3f(0.4f, -0.5f, -5.0f);
//    glVertex3f(-0.4f, -0.5f, -5.0f);
//
//    glEnd(); //End quadrilateral coordinates
//	glPopMatrix();
//
//    glBegin(GL_TRIANGLES); //Begin triangle coordinates
//    //Pentagon
//    glVertex3f(0.5f, 0.5f, -5.0f);
//    glVertex3f(1.5f, 0.5f, -5.0f);
//    glVertex3f(0.5f, 1.0f, -5.0f);
//
//    glVertex3f(0.5f, 1.0f, -5.0f);
//    glVertex3f(1.5f, 0.5f, -5.0f);
//    glVertex3f(1.5f, 1.0f, -5.0f);
//
//    glVertex3f(0.5f, 1.0f, -5.0f);
//    glVertex3f(1.5f, 1.0f, -5.0f);
//    glVertex3f(1.0f, 1.5f, -5.0f);
//
//    //Triangle
//    glVertex3f(-0.5f, 0.5f, -5.0f);
//    glVertex3f(-1.0f, 1.5f, -5.0f);
//    glVertex3f(-1.5f, 0.5f, -5.0f);
//
//    glEnd(); //End triangle coordinates
//    glfwSwapBuffers();*/
//
//}
//
//int main()
//{
//
//	GLuint VertexArrayID;
//	glGenVertexArrays(1, &VertexArrayID);
//	glBindVertexArray(VertexArrayID);
//
//
//	GLuint vertexbuffer;
//	// Generate 1 buffer, put the resulting identifier in vertexbuffer
//	glGenBuffers(1, &vertexbuffer);
//	// The following commands will talk about our 'vertexbuffer' buffer
//	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
//	// Give our vertices to OpenGL.
//	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
//
//	//glTranslatef( xValue, yValue, zValue );
//	//glRotatef(angleRotatation, xValue, yValue, zValue); 
//	//glScalef(xValue,yValue,zValue);
//
//	//int width, height;
//    //int frame = 0;
//    bool running = true;
//
//    initializeRendering();
//
//	glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); // 4x antialiasing
//	glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
//
//	//glfwOpenWindow(width, height, redbits, greenbits, bluebits, alphabits, depthbits, stencilbits, mode)
//    if( !glfwOpenWindow( 800, 800, 0, 0, 0, 0, 0, 0, GLFW_WINDOW ) ) 
//	//return false if window is not created
//    {
//        glfwTerminate(); //terminating glfw window
//        return -1;
//    }
//
//    glfwSetWindowTitle("Pinbaaaaaaaaaaaaaaaalllll");
//    glfwSetWindowSizeCallback(handleResize); //callback function of GLFW to handle window resize
//    //glfwSetKeyCallback(handleKeypress); //callback function to handle keypress
//
//	glfwEnable( GLFW_STICKY_KEYS );
//	do
//	{
//		// 1rst attribute buffer : vertices
//		glEnableVertexAttribArray(0);
//		glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
//		glVertexAttribPointer(
//		   0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
//		   3,                  // size
//		   GL_FLOAT,           // type
//		   GL_FALSE,           // normalized?
//		   0,                  // stride
//		   (void*)0            // array buffer offset
//		);
// 
//		// Draw the triangle !
//		glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
// 
//		glDisableVertexAttribArray(0);
// 
//		// Swap buffers
//		glfwSwapBuffers();
// 
//	} // Check if the ESC key was pressed or the window was closed
//	while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS && glfwGetWindowParam( GLFW_OPENED ) );	
//
//    return 0;
//}
//
////int main(void)
////{
////    /* Initialize the library */
////    if (!glfwInit())
////        return -1;
////
////    /* Create a windowed mode window and its OpenGL context */
////    if (!glfwOpenWindow(640, 480, 8, 8, 8, 0, 24, 0, GLFW_WINDOW))
////        return -1;
////
////    /* Loop until the user closes the window */
////    while (glfwGetWindowParam(GLFW_OPENED))
////    {
////		glBegin(GL_TRIANGLE_STRIP);
////		//glVertex2f( 1.0f, 1.0f );
////		//glVertex2f( P1.x, P1.y );
////		//glVertex2f( P2.x, P2.y );
////		//glVertex2f( P3.x, P3.y );
////		//glVertex2f( P4.x, P4.y );
////		//glVertex2f( P5.x, P5.y );
////		//glVertex2f( P6.x, P6.y );
////		//glVertex2f( P7.x, P7.y );
////		glEnd(); 
////        /* Render here */
////        /* Swap front and back buffers and process events */
////        glfwSwapBuffers();
////    }
////
////    return 0;
////}